#include "com_sct_screen_ScreenJni.h"
#include "screen.h"

#include <android/log.h>
#include <GLES/gl.h>

#include "sct/core/common.h"
#include "sct/core/mutex.h"

#define SCT_TAG "sct"

using namespace sct;

enum ScreenState
{
	SS_Terminated = SCT_ENUM_OFFSET,
	SS_Inited,
	SS_Running,
	SS_Stopped,
};

class CScreenInfo
{
public:
	CMutex * _mutex;

	int _state;

	int _width;
	int _height;

	uint8_t * _data;
	//int _len;
//	int _picWidth;
//	int _picHeight;
	int _maxLen;
	CPin _pin;

	///for interal use
//	uint8_t * _dData;
//	int _dLen;
//	int _dPicWidth;
//	int _dPicHeight;

	int _bNeedDeleteTexture;
	GLuint _textures[1];
};

static CScreenInfo * gScreenInfo = NULL;

JNIEXPORT void JNICALL Java_com_sct_screen_ScreenJni_create
  (JNIEnv *, jclass)
{
	if(NULL != gScreenInfo) return;

	gScreenInfo = new CScreenInfo;
	gScreenInfo->_mutex = new CMutex;

	gScreenInfo->_state = SS_Terminated;
	gScreenInfo->_width = 0;
	gScreenInfo->_height = 0;

	gScreenInfo->_bNeedDeleteTexture = 0;
	gScreenInfo->_textures[0] = -1;

	GLint mx;
	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mx);///the value is wrong.
	SCT_LOG("MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM22M:%d", mx);
	if(mx > 2048)
	{
		mx = 2048;
	}

	///RGBA
	gScreenInfo->_maxLen = mx * mx * 4;

	SCT_LOG("MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM22M:%d %d", mx, gScreenInfo->_maxLen);

	gScreenInfo->_data = new uint8_t[gScreenInfo->_maxLen];
	//gScreenInfo->_dData = new uint8_t[gScreenInfo->_maxLen];
//	gScreenInfo->_len = 0;
	gScreenInfo->_pin._mutex = new CMutex;
	gScreenInfo->_pin._data = gScreenInfo->_data;
	gScreenInfo->_pin._len = 0;
	gScreenInfo->_pin._picHeight = 0;
	gScreenInfo->_pin._picWidth = 0;


//	gScreenInfo->_picWidth = 0;
//	gScreenInfo->_picHeight = 0;

	gScreenInfo->_state = SS_Inited;
}

JNIEXPORT void JNICALL Java_com_sct_screen_ScreenJni_destroy
  (JNIEnv *, jclass)
{
	CMutex * p = gScreenInfo->_mutex;
	p->lock();

	if(gScreenInfo->_bNeedDeleteTexture)
	{
		glDeleteTextures(1, gScreenInfo->_textures);
		gScreenInfo->_bNeedDeleteTexture = 0;
	}

	SCT_DELETE(gScreenInfo->_pin._mutex);

	SCT_DELETE_ARRAY(gScreenInfo->_data);
	//SCT_DELETE_ARRAY(gScreenInfo->_dData);
	SCT_DELETE(gScreenInfo);

	p->unlock();
	SCT_DELETE(p);
}

//void sct_screen_putdata(void * d, const int len, const int w, const int h)
//{
//	CAutoLock locker(gScreenInfo->_mutex);
//
//	gScreenInfo->_len = len;
//	memcpy(gScreenInfo->_data, d, gScreenInfo->_len);
//
//	gScreenInfo->_picWidth = w;
//	gScreenInfo->_picHeight = h;
//}


JNIEXPORT void JNICALL Java_com_sct_screen_ScreenJni_tryToShowOneFrame
  (JNIEnv * env, jclass clx)
{
//	gScreenInfo->_pin._mutex->lock();
//	///move data in
//
//	gScreenInfo->_dLen = gScreenInfo->_pin._len;
//	gScreenInfo->_dPicWidth = gScreenInfo->_pin._picWidth;
//	gScreenInfo->_dPicHeight = gScreenInfo->_pin._picHeight;
//	if(gScreenInfo->_dLen > 0)
//	{
//		memcpy(gScreenInfo->_dData, gScreenInfo->_pin._data, gScreenInfo->_dLen);
//	}
//
//	gScreenInfo->_pin._mutex->unlock();

	CAutoLock locker(gScreenInfo->_mutex);

	if(gScreenInfo->_pin._len > 0)
	{
		//gScreenInfo->_pin._len = 0;

		///init for draw
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		//glTranslatef(0.0f, 0.0f, -1.2f);


		///delete old texture and create a new one
		if(gScreenInfo->_bNeedDeleteTexture)
		{
			glDeleteTextures(1, gScreenInfo->_textures);
			gScreenInfo->_bNeedDeleteTexture = 0;
		}

		glGenTextures(1, gScreenInfo->_textures);
		gScreenInfo->_bNeedDeleteTexture = 1;

		glBindTexture(GL_TEXTURE_2D, gScreenInfo->_textures[0]);

		GLint mx;
		glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mx);
		//mx = 1600;
		//SCT_LOG("MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMyyyyyyyyyyyyyyyyy:%d", mx);
		mx = 1024;

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mx, mx, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

		gScreenInfo->_pin._mutex->lock();
//		double tu1 = currentTime();
//
//		double tu8 = currentTime();
		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, gScreenInfo->_pin._picWidth, gScreenInfo->_pin._picHeight, GL_RGBA, GL_UNSIGNED_BYTE, gScreenInfo->_data);
//		double tu9 = currentTime();
//		tu9 -= tu8;
//		if(tu9 > 0.02)
//		{
//			SCT_LOG("GGGGGGGGGGGGGGGGGG22GGGGGGGTTTTTTTTTTT33TTTT:%f", tu9);
//		}
//
//
//		double tu2 = currentTime();
//		tu2 -= tu1;
//		if(tu2 > 0.02)
//		{
//			SCT_LOG("GGGGGGGGGGGGG55GGGGGGGGG222GGGGGGGGGGGGGGGGGGGGG:%f", tu2);
//		}

		int w = gScreenInfo->_pin._picWidth;
		int h = gScreenInfo->_pin._picHeight;

		gScreenInfo->_pin._mutex->unlock();

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


//		{
//			int w, h;
//				w = h = 512;
//				w = 1024;
//				h = 720;
//
//				GLubyte * d = NULL;
//
//				d = new GLubyte[w * h * 4];
//
//			    //just for test
//				for(int i = 0; i<h; i++)
//				{
//					if( i < 32 )
//					{
//						for(int j= 0; j<w; j++)
//						{
//							GLubyte b0 = 0;
//							GLubyte b1 = (GLubyte)255;
//
//							d[i * w * 4 + j*4 + 0] = b0;
//							d[i * w * 4 + j*4 + 1] = b1;
//							d[i * w * 4 + j*4 + 2] = b0;
//							d[i * w * 4 + j*4 + 3] = b0;
//
//						}
//					}
//					else
//					{
//						for(int j= 0; j<w; j++)
//						{
//							GLubyte b0 = 0;
//							GLubyte b1 = (GLubyte)255;
//
//							d[i * w * 4 + j*4 + 0] = b0;
//							d[i * w * 4 + j*4 + 1] = b0;
//							d[i * w * 4 + j*4 + 2] = b0;
//							d[i * w * 4 + j*4 + 3] = b0;
//						}
//					}
//				}
//				//glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, d);
//				//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, d);
//
//
//				delete[]d;
//		}


		GLfloat textureCoords[8] =
		{
                0.0f, 1.0f,
                1.0f, 1.0f,

                0.0f, 0.0f,
                1.0f, 0.0f,
		};



		textureCoords[0] = 0.0;			textureCoords[1] = (1.0*h)/mx;
		textureCoords[2] = (1.0*w)/mx;	textureCoords[3] = (1.0*h)/mx;
		textureCoords[4] = 0.0;			textureCoords[5] = 0.0;
		textureCoords[6] = (1.0*w)/mx;	textureCoords[7] = 0.0;

		glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);



        float vertices[] =           //2
		{
				-1.0f, -1.0f,
				1.0f, -1.0f,
				-1.0f,  1.0f,
				1.0f,  1.0f
		};

        float x = 1;
        float y = 1;

        float winRatio = (1.0*gScreenInfo->_height)/(1.0*gScreenInfo->_width);
        float picRatio = (1.0*h) / w;

        if(winRatio > picRatio)
        {
        	x = 1;
        	y = picRatio;
        }
        else
        {
        	x = 1 * (winRatio/picRatio);
        	y = winRatio;
        }


        vertices[0] = -x;	vertices[1] = -y;
        vertices[2] = x;	vertices[3] = -y;
        vertices[4] = -x;	vertices[5] = y;
        vertices[6] = x;	vertices[7] = y;

        glVertexPointer(2, GL_FLOAT, 0, vertices);

        glEnable(GL_TEXTURE_2D);

        //glEnable(GL_BLEND);
        glBlendFunc(GL_ONE, GL_SRC_COLOR);

        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);
	}
	else
	{
		//gScreenInfo->_pin._mutex->unlock();
	}
}

JNIEXPORT void JNICALL Java_com_sct_screen_ScreenJni_configScreen
  (JNIEnv * env, jclass clx, jint w, jint h, jint t)
{
	CAutoLock locker(gScreenInfo->_mutex);
	gScreenInfo->_state = SS_Running;

	gScreenInfo->_width = w;
	gScreenInfo->_height = h;

	glDisable(GL_DITHER);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

	if(t)
	{
		glClearColor(0, 0, 0, 0);
	}
	else
	{
		glClearColor(1, 1, 1, 1);
	}

	glEnable(GL_CULL_FACE);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);

	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	float x = 1.0;
	float y = (1.0 * h)/w;

	//in the center
	glOrthof(-x, x, -y, y, 1, -1);

	//SCT_LOG("==========================================================%f   %f", y, 1.0*gScreenInfo->_picHeight/gScreenInfo->_picWidth);
	//float ratio = (1.0 * w) / h;
	//glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}


sct::CPin* sct_screen_getPin()
{
	CAutoLock locker(gScreenInfo->_mutex);
	return & gScreenInfo->_pin;
}













